#include "XDemuxThread.h"
#include "XDemux.h"
#include "XVideoThread.h"
#include "XAudioThread.h"
#include <QDebug>
#include "XDecode.h"
extern "C" {
	#include <libavformat/avformat.h>
}
struct AVPacket;

void XDemuxThread::SetPause(bool isPause)
{
	this->Pause = isPause;
	if(at) at->SetPause(isPause);
	if (vt) vt->SetPause(isPause);
}

void XDemuxThread::run()
{
	while (!isExit) {
		if (Pause) {
			msleep(5);
			continue;
		}
		demux_thread_mutex.lock();
		
		if (!demux) {
			demux_thread_mutex.unlock();
			msleep(1);
			continue;
		}
		//音视频同步
		if (vt && at) {
			pts = at->pts;
			vt->synpts = at->pts;
			//qDebug() << "synpts = " << vt->synpts;
		}

		AVPacket *pkt = demux->Read();
		if (!pkt) {
			demux_thread_mutex.unlock();
			msleep(1);
			continue;
		}
		if (demux->IsAudio(pkt)) {
			if (at != NULL) {
				at->Push(pkt);
			}
		}
		else {
			if (vt != NULL) {
				vt->Push(pkt);
			}

		}
		demux_thread_mutex.unlock();
	}
}

bool XDemuxThread::Open(const char * url, IVideoCall * call)
{
	if (url == NULL) {
		return false;
	}
	demux_thread_mutex.lock();
	
	//打开解封装
	bool ret = demux->Open(url);
	if (!ret) {
		qDebug() << "demux->open failed";
		return false;
	}
	//打开视频解码器和处理线程
	if (vt->Open(demux->CopyVPara(), call, demux->width, demux->height) == false) {
		ret = false;
		qDebug() << "vt->Open failed";
	}
	//打开音频解码器和处理线程
	if (!at->Open(demux->CopyAPara(), demux->sampleRate, demux->channels)) {
		ret = false;
		qDebug() << "at->Open failed";
	}
	totalMs = demux->totalMs;
	demux_thread_mutex.unlock();
	qDebug() << "XdemuxThread::Open" << ret;
	return ret;
}

void XDemuxThread::Start()
{
	demux_thread_mutex.lock();
	//启动当前线程
	if (!demux) {
		demux = new XDemux();
	}
	if (!vt) {
		vt = new XVideoThread();
	}
	if (!at) {
		at = new XAudioThread();
	}
	QThread::start();
	if (vt) {
		vt->start();
	}
	if (at) {
		at->start();
	}
	demux_thread_mutex.unlock();
}

void XDemuxThread::Close()
{
	isExit = true;
	wait();
	if (vt) vt->Close();
	if (at) at->Close();
	demux_thread_mutex.lock();
	delete vt;
	delete at;
	vt = NULL;
	at = NULL;
	demux_thread_mutex.unlock();
	
}

void XDemuxThread::Clear()
{
	demux_thread_mutex.lock();
	if (demux) {
		demux->Clear();
	}
	if (vt) vt->Clear();
	if (at) at->Clear();
	demux_thread_mutex.unlock();
}

void XDemuxThread::Seek(double pos)
{
	//清理缓冲
	Clear();
	//demux_thread_mutex.lock();
	bool status = this->Pause;
	//demux_thread_mutex.unlock();

	//全部暂停
	SetPause(true);

	demux_thread_mutex.lock();
	if (demux) {
		demux->Seek(pos);
	}

	//实际要显示的位置pts
	long long seekPts = pos * demux->totalMs;
	while (!isExit) {
		AVPacket *pkt = demux->ReadVideo();
		if (!pkt) {
			break;
		}
		//如果解码到seekpts
		if (vt->RepaintPts(pkt, seekPts)) {
			this->pts = seekPts;
			break;
		}
	}


	demux_thread_mutex.unlock();

	if (!status)
		SetPause(false);
	
}



XDemuxThread::XDemuxThread()
{
}

XDemuxThread::~XDemuxThread()
{
	isExit = true;
	wait();
}


